/***************************************************************************************************
  *Copyright(C),2010-2017,Sumscope
  *FileName	:  StopCodec.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2019/09/11
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#ifndef STOPCODEC_H_ADCB35EB_CD05_4BD4_9853_2D0DCEBB78B4
#define STOPCODEC_H_ADCB35EB_CD05_4BD4_9853_2D0DCEBB78B4
#include "TableCodecCommon.h"
#include <cstring>
#include <climits>
//#include "SSBase/strings/string_page.h"
namespace qb{
	namespace proto{
		class TableCodec;
		class SSPROTOAPI VariantDouble{
			enum kStepMode{
				kStepModeValid,
				kStepModeFill,
				kStepModeDelta,
				kStepModeTail
			};
		public:
			static int ParsePrecision(const char* buf, int len);
			static bool ConvertDouble(double d, i64& val, int& width);
			static bool ConvertDoubleEx(double d, i64& val, int& width);
			static bool ConvertFloat(float f, int& val, int& width);
			static int EncodeFloat(unsigned char* buf, int capcity, float d);
			static int DecodeFloat(const unsigned  char* buf, int capcity, float& d);
			static int Encode(unsigned char* buf, int capcity, double d);
			static int Decode(const unsigned  char* buf, int capcity, double& d);
			static int CalcSize(double d);
		};

		class SSPROTOAPI VarAllocator{
		public:
			virtual ~VarAllocator(){}
			virtual void Reset() = 0;
			virtual char* AllocString(const char* str, int len) = 0;
		};
		class OnceAllocator{
			class Block{
				char*	m_buffer;
				int		m_used;
				int		m_capcity;
			public:
				Block(int capcity) :m_capcity(capcity), m_buffer(NULL), m_used(0){
					m_buffer = new char[m_capcity];
					memset(m_buffer, 0, m_capcity);
				}
				~Block()
				{
					if (m_buffer)delete[] m_buffer;
					m_buffer = NULL;
				}
				bool IsFull(int size)const
				{
					return m_used + size + 1 > m_capcity;
				}
				const char* AddStr(const char* str, int len)
				{
					int size = strlen(str);
					size = size > len ? len : size;
					char* buf = m_buffer + m_used;
					memcpy(buf, str, size);
					buf[size] = 0;
					buf[len] = 0;
					m_used += len+1;
					return buf;
				}
			};
			std::vector<Block*>	m_cache;
			Block*			m_block;
		public:
			OnceAllocator() :m_block(NULL)
			{

			}
			~OnceAllocator()
			{
				Reset();
			}
			void Reset()
			{
				for (int i = 0; i < (int)m_cache.size(); i++)
				{
					delete m_cache[i];
				}
				m_cache.clear();
				if (m_block)
					delete m_block;
				m_block = NULL;
			}
			const char* AddString(const char* str, int size)
			{
				if (m_block && !m_block->IsFull(size))
					return m_block->AddStr(str, size);
				if (m_block)
					m_cache.push_back(m_block);
				int cap = 4096 * 4;
				if (cap < size)cap += size;
				m_block = new Block(cap);
				return m_block->AddStr(str, size);
			}
		};
		class DefaultVarAllocator : public VarAllocator{
			OnceAllocator			m_page;
		public:
			virtual ~DefaultVarAllocator(){}
			virtual void Reset(){ m_page.Reset(); }
			virtual char* AllocString(const char* str, int len)
			{
				return const_cast<char*>(m_page.AddString(str, len));
			}
		};
		class SSPROTOAPI StopCodec{
			unsigned char*			m_buffer;		// 外部拥有,析构时不能删除
			int						m_capcity;		// m_buffer大小
			int						m_pos;			// 当前解析
			bool					m_write;
			std::vector<unsigned char>	m_bytes;
		public:
			StopCodec(unsigned char* buf, int capcity,bool write);
			int GetPos()const;
			void Init(unsigned char* buf, int capcity, bool write);
		public:

			// 预估VarValue值编码成类型kEncodeType的大小,如果不能,返回-1
			// 注意,返回0不等同于-1,返回0表示编码不需要占用空间,是默认值,需要用OpBitmapFlag
			// 返回-1,表示此编码类型不支持此值val
			static int CalcEncodeSize(kEncodeType type, const VarValue& val);
			static inline ui64 ToZigzag(i64 n)
			{
				return (ui64)((n << 1) ^ (n >> (sizeof(n)*CHAR_BIT - 1))); //int64符号位右移63
			}
			static inline i64 FromZigzag(ui64 n)
			{
				return (i64)((((ui64)n) >> 1) ^ (-((i64)n & 1)));
			}

			// 解码当前内容长度
			static inline int DecodeLength(const unsigned char* buf, int capcity)
			{
				for (int i = 0; i < capcity; i++){
					if (buf[i] & StatusEnd)
						return i + 1;
				}
				return capcity;
			}
			int EncodeBytes(const unsigned char* buf, int size,int bitwidth);
			int DecodeBytes(std::vector<unsigned char>& buf, int bitWidth);
		public://编码
			int AddValue(kEncodeType type, const VarValue& value);
			
		public:// 解码
			bool GetValue(kEncodeType type, VarValue& value, VarAllocator* allocator);
			i64 GetInt(int failedValue = -1);

		private:
			int EncodeTypeStr(kEncodeType type, const VarValue& value, int bitwidth, bool use_ascii_map);
			int EncodeTypeVarInt(kEncodeType type, const VarValue& value);

			bool DecodeTypeStr(kEncodeType type, VarValue& value, int bitwidth, VarAllocator* allocator, bool use_ascii_map);
			bool DecodeTypeVarInt(kEncodeType type, VarValue& value);
			int EncodeVarUint(ui64 nTmp);
			ui64 DecodeVarUint();
		};

	}//namespace base;
}//namespace ss;



#endif
